

import java.io.ByteArrayInputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;


public class Controle {

	public HashMap<String,Integer> argFctPredefinie = new HashMap<String,Integer>();
	
	public HashMap<String,Method> methodFctPredefinie = new HashMap<String,Method>();
	
	public Controle() {
		argFctPredefinie.put("si", 2);
		argFctPredefinie.put("sinon", 3);
		argFctPredefinie.put("repete", 2);
		argFctPredefinie.put("ecris", 1);
		argFctPredefinie.put("tantque", 2);
		argFctPredefinie.put("repetepour", 2);
		
		Class c = Controle.class;
		Method[] tab = c.getMethods();
		
		Method  m;
		for (int i=0;i<tab.length;i++) {
			m = tab[i];
	
			if(m.getName().equals("si"))
				methodFctPredefinie.put("si", m);
			
			if(m.getName().equals("sinon"))
				methodFctPredefinie.put("sinon", m);
			
			if(m.getName().equals("repete"))
				methodFctPredefinie.put("repete", m);
	
			if(m.getName().equals("ecris"))
				methodFctPredefinie.put("ecris", m);
			
			if(m.getName().equals("tantque"))
				methodFctPredefinie.put("tantque", m);
			
			if(m.getName().equals("repetepour"))
				methodFctPredefinie.put("repetepour", m);
		}    
	};
	
	
	public static String listToString(ArrayList l){
		String list = "[ ";
		
		for(int i=0; i<l.size();i++){
			if(l.get(i) instanceof ArrayList)
				list += listToString((ArrayList)l.get(i))+" ";
			else
				list += l.get(i) +" ";
		}
		list += "]";
		return list;
	}
	
	public static Object run(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
			
		String list = (String)v.get(0);
		
		list = list.substring(1, list.length()-1);
		//System.out.println("stream : "+list);
		ByteArrayInputStream stream  = new ByteArrayInputStream(list.getBytes());

        ParserLogo parser = new ParserLogo(stream);
        parser.initEnv(penv);
        
        return parser.run();
	}
	
	
	public static Object si(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		ArrayList<Object> o = new ArrayList<Object>();

		HashMap<String, Object> env = new HashMap<String, Object>();
		
		env.put("env_sup",penv);
		
		if((v.get(0) instanceof Boolean)  && v.get(1) instanceof ArrayList  && v.size()==2) {
			if ((Boolean)v.get(0)){
				o.add(listToString((ArrayList)v.get(1)));
				return run(o,env);
			}
			else
				return false;
		}
		else
			return false;
	}
	
	
	public static Object sinon(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		ArrayList<Object> o = new ArrayList<Object>();
		
HashMap<String, Object> env = new HashMap<String, Object>();
		
		env.put("env_sup",penv);
		
		if((v.get(0) instanceof Boolean)  && v.get(1) instanceof ArrayList  && v.size()==3) {
			if ((Boolean)v.get(0)) {
				o.add(listToString((ArrayList)v.get(1)));
				return run(o,env);
			}
			else {
				if(v.get(2) instanceof ArrayList) {
					o.add(listToString((ArrayList)v.get(2)));
					return run(o,env);
				}
				return false;
			}
		}
		else
			return false; 
	}
	
	
	public static Object repete(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		ArrayList<Object> o = new ArrayList<Object>();
		Object ret = null;
		String list;
		
		HashMap<String, Object> env = new HashMap<String, Object>();
		env.put("env_sup",penv);
		
		if((v.get(0) instanceof Integer)  && v.get(1) instanceof ArrayList  && v.size()==2) {
			
			list = listToString((ArrayList)v.get(1));
			list = list.substring(1, list.length()-1);
			byte[] b = list.getBytes();
			ByteArrayInputStream stream  = new ByteArrayInputStream(b);
			ParserLogo parser = new ParserLogo(stream);
			
			for(int i=0; i<(Integer)v.get(0); i++) {
			
				stream  = new ByteArrayInputStream(b);
				parser.ReInit(stream);
				parser.initEnv(penv);
		        
		        ret = parser.run();
			}
		}
			
		return ret;
	}
	
	
	
	
	public  static Object ecris(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		
		if(v.size()==1) {
			if(v.get(0) instanceof ArrayList) 
				System.out.println(listToString((ArrayList)v.get(0)));
			else
				System.out.println(v.get(0));
			return true;
		}
		else 
			return false;
		
	}
	
	
	
	public static Object tantque(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		ArrayList<Object> o = new ArrayList<Object>();
		ArrayList<Object> o2 = new ArrayList<Object>();
		Object ret = null;

		HashMap<String, Object> env = new HashMap<String, Object>();
		
		env.put("env_sup",penv);
		
		if(v.size() == 2 && v.get(0) instanceof ArrayList && v.get(1) instanceof ArrayList) {
			o.add(listToString((ArrayList)v.get(0)));
			o2.add(listToString((ArrayList)v.get(1)));
			while((Boolean)run(o,env)) {
				ret = run(o2,env);
			}
		}
			
		return ret;
	}
	
	
	public static Object repetepour(ArrayList<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		ArrayList<Object> o = new ArrayList<Object>();
		ArrayList<Object> l = new ArrayList<Object>();
		Object ret = null;
	
		
		HashMap<String, Object> env = new HashMap<String, Object>();
		
		env.put("env_sup",penv);
		
		if(v.size() == 2 && v.get(0) instanceof ArrayList && v.get(1) instanceof ArrayList) {
			String list = listToString((ArrayList)v.get(0));
			
			list = list.substring(1, list.length()-1);
			ByteArrayInputStream stream  = new ByteArrayInputStream(list.getBytes());

	        ParserLogo parser = new ParserLogo(stream);
	        parser.initEnv(penv);
	        
	        l = (ArrayList)parser.runList();
			
			if(l.size() == 3 || l.size() == 4){
				int borne = (Integer)l.get(2);
				String interateur = (String)l.get(0);
				o.add(listToString((ArrayList)v.get(1)));
			
				int pas = 1; 
				
				if(l.size() == 4)
					pas = (Integer)l.get(3);
				
				for(int n = (Integer)l.get(1); n<borne; n+=pas) {
					penv.put(interateur,n);
					ret = run(o,env);
				}
				penv.remove(interateur);
			}	
		}
		return ret;	
	}
	
	
	}
